home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / SK (Sockects) 1.4.1 r2 / SK v1.4.1 r2.sit / SK 1.4.1 r2 / SK / SK Sources / SK_Dispatch.cc < prev    next >
C/C++ Source or Header  |  1994-06-13  |  53KB  |  2,421 lines

  1. /***************************************************************************
  2. * Copyright ⌐ 1992-1994 Matthias Neeracher and the Decision Systems Group
  3. * Permission is granted to anyone to use this software for any purpose on
  4. * any computer system, and to redistribute it freely, subject to the
  5. * following restrictions:
  6. * 1) The authors and the Decision Systems Group are not responsible for 
  7. *    the direct or indirect consequences of use of this software, no matter 
  8. *    how awful, even if they arise from defects in the software itself.
  9. *    This restriction applies to the use of this and any derived source code 
  10. *    and also to the use of all binary produced from this and any derived 
  11. *    source code.
  12. * 2) The origin and copyrights of this software must not be misrepresented, 
  13. *    either by explicit claim or by omission or alteration of copyright or
  14. *    authorship header information in this file or in any derived file.
  15. * 3) Altered or derived versions must be plainly marked as such, and must not
  16. *    be misrepresented as being the original software.
  17. * We encourage users of this software to provide feedback, bug fixes,
  18. * and enhancements to the authors for incorporation into future releases.
  19. *
  20. * ==========================================================================
  21. * FILE: SK_Dispatch.cc
  22. * AUTHOR: Matthias Neeracher and Stephan Deibel
  23. * CREATION DATE: 24Mar92
  24. * VERSION: 13Jun94
  25. * DESCRIPTION: 
  26. * Dispatch routines for C calls to C++ objects
  27. * NOTES: 
  28. * 0) This code was derived from Matthias Neerarcher's GUSI 1.1.0; Copyrights
  29. *    are subject to that fact.
  30. *
  31. * MODIFICATIONS: 
  32. * --------------------------------------------------------------------------
  33. * Date     Name      Description of modification
  34. * --------------------------------------------------------------------------
  35. * 31Mar92    MN       unix domain socket calls
  36. * 16Apr92    MN       User interrupt stuff
  37. * 17Apr92    MN       Spin routines
  38. * 18Apr92    MN       Changed read/write/send/recv dispatchers
  39. * 19Apr92    MN       C++ Rewrite
  40. * 06Jun92    MN       CSK_Feature
  41. * 27Jun92    MN       choose(), SKg_NewSF
  42. * 13Jul92    MN       SKg_ProcessMgr
  43. * 30Jul92    MN       Features with initializers
  44. * 03Aug92    MN       Move Scatter/Gather to SK_Buffer.cc
  45. * 05Aug92    MN       Change the way standard I/O channels are opened
  46. * 30Aug92    MN       Move SKg_PPC to SK_PPC.cp, AppleTalkIdentity
  47. * 12Sep92    MN       SK_getdtablesize()
  48. * 05Oct92    MN       Small fix in event dispatching
  49. * 25Nov92    MN       Still trying to get standard descriptors for standalone programs right. sigh.
  50. * 03Jan93    MN       CSK_Configuration
  51. * 17Jan93    MN       Be more careful about user aborts.
  52. * 31Jan93    MN       Introducing daemons (pleased to meet you, hope you guess my name)
  53. * 13Jul93    SD       Port to THINK C++ 6.0
  54. * 21Jul93    SD       Subsetted to only TCP/UDP, applied DSG naming 
  55. *                    conventions and commenting guidelines, and
  56. *                    changed name to "SK" for clear distinction from
  57. *                    the GUSI code from which this was derived
  58. * 13Jun94   SD       Updated based on relevant changes to GUSI (through 1.4.1)
  59. */
  60.  
  61. #include <stdio.h>
  62. #include "SK_P.hh"
  63. #include "SetJmp.h"
  64. #include "Signal.h"
  65. // #include "CursorCtl.h"
  66. #include "Resources.h"
  67. #include "Events.h"
  68. #include "Windows.h"
  69. #include "Desk.h"
  70. #include "Script.h"
  71. #include "OSEvents.h"
  72. #include "Traps.h"
  73. #include "CommResources.h"
  74. #include "CTBUtilities.h"
  75. #include "Connections.h"
  76. #include "FileTransfers.h"
  77. #include "Terminals.h"
  78. #include "EPPC.h"
  79. #include <AppleEvents.h>
  80.  
  81. // Extra "extern"s
  82. extern "C" int file_open(const char * name, int flags);
  83. extern Boolean IsDevice(const char * fn);
  84.  
  85. // If STANDALONE is not defined anywhere, then we assume that this is a daemon
  86. // server program
  87. #ifndef STANDALONE
  88. #define STANDALONE FALSE
  89. #endif
  90.  
  91. /**************************************************************************/ 
  92. /**************************************************************************/ 
  93. /* Globals */
  94.  
  95. // SK configuration object and table of active sockets
  96. // IMPORTANT NOTE: Changing the order of these two globals will prevent proper initialization!
  97. // NOTE ALSO: The SKg_Config variable SHOULD be 'const' but adding this under Symantec C++ 7.0
  98. //    results in a link error (undefined).
  99. CSK_Configuration SKg_Config;            
  100. CSK_SocketTable SKg_SocketTable;
  101.  
  102. // SK spin routine for handling idle time during waits on sockets
  103. SKt_SpinFn SKg_SpinRoutine = &SK_DefaultSpinRoutine;
  104.  
  105. // SK event handler used by idle time spin routine
  106. static SKt_EvtHandler *SKg_EventHandler = NULL;
  107.  
  108. // Event mask used by SK event handler
  109. static short SKg_EvtMask = 0;
  110.  
  111. // ??? 
  112. static int SKg_ErrorSock = -1;
  113. static int SKg_ErrorType = 0;
  114. static int SKg_ErrorCount = 0;
  115. const int SKg_ErrorMax = 3;
  116.  
  117. // Feature availability globals.
  118.  
  119. CSK_Feature SKg_MakeFSSpec(
  120.                 gestaltFSAttr,
  121.                 (1<<gestaltHasFSSpecCalls),
  122.                 (1<<gestaltHasFSSpecCalls));
  123. CSK_Feature SKg_Alias(
  124.                 gestaltAliasMgrAttr,
  125.                 (1<<gestaltAliasMgrPresent),
  126.                 (1<<gestaltAliasMgrPresent));
  127. CSK_Feature    SKg_WNE((short) _WaitNextEvent, (TrapType) ToolTrap);
  128. CSK_Feature    SKg_NewSF(
  129.                 gestaltStandardFileAttr,
  130.                 (1<<gestaltStandardFile58),
  131.                 (1<<gestaltStandardFile58));
  132. CSK_Feature SKg_ProcessMgr(
  133.                 gestaltOSAttr,
  134.                 (1<<gestaltLaunchControl),
  135.                 (1<<gestaltLaunchControl));
  136. CSK_Feature SKg_CRM_P(
  137.                 gestaltCRMAttr,
  138.                 (1<<gestaltCRMPresent),
  139.                 (1<<gestaltCRMPresent));
  140. CSK_Feature SKg_CRM(SKg_CRM_P, InitCRM);
  141. CSK_Feature SKg_CTB(SKg_CRM, InitCTBUtilities);
  142. CSK_Feature SKg_StdNBP_P(
  143.                 gestaltStdNBPAttr,
  144.                 (1<<gestaltStdNBPPresent),
  145.                 (1<<gestaltStdNBPPresent));
  146. CSK_Feature SKg_StdNBP(SKg_CTB, SKg_StdNBP_P);
  147. CSK_Feature SKg_CM(SKg_CTB, InitCM);
  148. CSK_Feature SKg_FT(SKg_CTB, InitFT);
  149. CSK_Feature SKg_TM(SKg_CTB, InitTM);
  150. CSK_Feature SKg_AppleEvents(
  151.                 gestaltAppleEventsAttr,
  152.                 (1<<gestaltAppleEventsPresent),
  153.                 (1<<gestaltAppleEventsPresent));
  154. CSK_Feature SKg_RevisedTimeMgr(
  155.                 gestaltTimeMgrVersion,
  156.                 2L);
  157.  
  158.  
  159.  
  160. /**************************************************************************/ 
  161. /**************************************************************************/ 
  162. /* Implementation of external sockets interface routines -- These act as 
  163. *  the "glue" between the straight "C" calling interface and the C++
  164. *  internals of this package
  165. */
  166.  
  167.  
  168. /*************************************************************************** *
  169. * FUNCTION:
  170. *
  171. * SK_getdtablesize
  172. *
  173. * DESCRIPTION:
  174. *
  175. * Return the maximum number of file descriptors -- the size of any descriptor
  176. * table in this package.
  177. *
  178. * RETURNS:
  179. *
  180. * int            -- The max number of file descriptors
  181. *
  182. */
  183.  
  184. int SK_getdtablesize()
  185. {
  186.     return SKk_MaxFD;
  187. }
  188.  
  189.  
  190. /*************************************************************************** *
  191. * FUNCTION:
  192. *
  193. * SK_socket
  194. *
  195. * DESCRIPTION:
  196. *
  197. * Allocate a socket of given domain, type, and protocol
  198. *
  199. * PARAMETERS:
  200. *
  201. * int            -- The domain for new socket
  202. * int            -- The type of new socket
  203. * short            -- The protocol for new socket
  204. *
  205. * RETURNS:
  206. *
  207. * int            -- The file descriptor for the new socket, or -1 upon failure
  208. *
  209. */
  210.  
  211. int SK_socket(int domain, int type, int protocol)
  212. {
  213.     CSK_SocketDomain * dom;
  214.     CSK_Socket * sock;
  215.     int    fd;
  216.  
  217.     dom = CSK_SocketDomain::Domain(domain);
  218.     if (dom != NULL)
  219.         sock = dom->socket(type, protocol);
  220.         if (sock != NULL)
  221.             if ((fd = SKg_SocketTable.Install(sock)) != -1)
  222.                 return fd;
  223.             else
  224.                 delete sock;
  225.  
  226.     return -1;
  227. }
  228.  
  229.  
  230. /*************************************************************************** *
  231. * FUNCTION:
  232. *
  233. * SK_bind
  234. *
  235. * DESCRIPTION:
  236. *
  237. * Bind the given socket to the given internet host name
  238. *
  239. * PARAMETERS:
  240. *
  241. * int                            -- The socket file descriptor
  242. * const struct sockaddr *        -- Pointer to internet address name
  243. * int                            -- Length of name (null terminator is NOT used)
  244. *
  245. * RETURNS:
  246. *
  247. * If the binding succeeds, then 0 is returned. Otherwise a -1 is returned, 
  248. * and a more specific error code is stored in errno (see appropriate socket 
  249. * type for details).
  250. *
  251. */
  252.  
  253. int SK_bind(int s, const struct sockaddr *name, int namelen)
  254. {
  255.     CSK_Socket *sock = SKg_SocketTable[s];
  256.  
  257.     return sock ? sock->bind((void *) name, namelen) : -1;
  258. }
  259.  
  260.  
  261. /*************************************************************************** *
  262. * FUNCTION:
  263. *
  264. * SK_connect
  265. *
  266. * DESCRIPTION:
  267. *
  268. * Connect the given socket to the given internet address (ip number)
  269. *
  270. * PARAMETERS:
  271. *
  272. * int                            -- The socket file descriptor
  273. * const struct sockaddr *        -- The internet address
  274. * int                            -- The length of the internet address
  275. *
  276. * RETURNS:
  277. *
  278. * If the connection succeeds, then 0 is returned. Otherwise a -1 is returned, 
  279. * and a more specific error code is stored in errno (see appropriate socket 
  280. * type for details).
  281. *
  282. */
  283.  
  284. int SK_connect(int s, const struct sockaddr *addr, int addrlen)
  285. {
  286.     CSK_Socket *sock = SKg_SocketTable[s];
  287.     return sock ? sock->connect((void *) addr, addrlen) : -1;
  288. }
  289.  
  290.  
  291. /*************************************************************************** *
  292. * FUNCTION:
  293. *
  294. * SK_listen
  295. *
  296. * DESCRIPTION:
  297. *
  298. * Listen on the given socket
  299. *
  300. * PARAMETERS:
  301. *
  302. * int            -- The socket file descriptor
  303. * int            -- unused
  304. *
  305. * RETURNS:
  306. *
  307. * If listening succeeds, then 0 is returned. Otherwise a -1 is returned, 
  308. * and a more specific error code is stored in errno (see appropriate 
  309. * socket type for details).
  310. *
  311. */
  312.  
  313. int SK_listen(int s, int qlen)
  314. {
  315.     CSK_Socket *sock = SKg_SocketTable[s];
  316.  
  317.     return sock ? sock->listen(qlen) : -1;
  318. }
  319.  
  320.  
  321. /*************************************************************************** *
  322. * FUNCTION:
  323. *
  324. * SK_accept
  325. *
  326. * DESCRIPTION:
  327. *
  328. * Accept a connection request on the given socket
  329. *
  330. * PARAMETERS:
  331. *
  332. * int                    -- The socket file descriptor
  333. * struct sockaddr *     -- Pointer to memory for address return value
  334. * int *                    -- Pointer to memory for return value (initialized
  335. *                           to space available in address return buffer)
  336. *
  337. * RETURNS:
  338. *
  339. * int                    -- The socket file descriptor of the new socket created
  340. *                           to handle the newly established connection.  The old
  341. *                           socket is kept active so that additional connections
  342. *                          can be made to it by other clients.
  343. * struct sockaddr *     -- 2nd parameter: The internet number connection was made from
  344. * int *                    -- 3rd parameter: Length of above internet address
  345. *
  346. */
  347.  
  348. int SK_accept(int s, struct sockaddr *addr, int *addrlen)
  349. {
  350.     CSK_Socket *sock = SKg_SocketTable[s];
  351.  
  352.     if (sock != NULL)
  353.         sock = sock->accept(addr, addrlen);
  354.         if (sock != NULL)
  355.             if ((s = SKg_SocketTable.Install(sock)) != -1)
  356.                 return s;
  357.             else
  358.                 delete sock;
  359.  
  360.     return -1;
  361. }
  362.  
  363.  
  364. /****************************************************************************
  365. * FUNCTION:
  366. *
  367. * SK_close
  368. *
  369. * DESCRIPTION:
  370. *
  371. * Close connection on given socket
  372. *
  373. * PARAMETERS:
  374. *
  375. * int            -- The socket file descriptor
  376. *
  377. * RETURNS:
  378. *
  379. * int             -- Error value (0 = no error)
  380. *
  381. */
  382.  
  383. int SK_close(int s)
  384. {
  385.     SKg_ErrorSock = -1;
  386.     
  387.     return SKg_SocketTable.Remove(s);
  388. }
  389.  
  390.  
  391. /****************************************************************************
  392. * FUNCTION:
  393. *
  394. * SK_read
  395. *
  396. * DESCRIPTION:
  397. *
  398. * Read bytes from the given socket using a plain buffer.
  399. *
  400. * PARAMETERS:
  401. *
  402. * int            -- The socket file descriptor
  403. * char *        -- Pointer to buffer memory
  404. * unsigned        -- Length of available buffer memory
  405. *
  406. * RETURNS:
  407. *
  408. * Bytes read are returned in the given buffer memory.  The integer
  409. * function return value is the number of bytes actually received (-1 = error).
  410. *
  411. */
  412.  
  413. int SK_read(int s, char *buffer, unsigned buflen)
  414. {
  415.     SKg_Config.DoAutoSpin();
  416.     
  417.     CSK_Socket *sock = SKg_SocketTable[s];
  418.  
  419.     return sock ? sock->read(buffer, buflen) : -1;
  420. }
  421.  
  422.  
  423. /****************************************************************************
  424. * FUNCTION:
  425. *
  426. * SK_readv
  427. *
  428. * DESCRIPTION:
  429. *
  430. * Read bytes from the given socket using a BSD Unix iovec structure.
  431. *
  432. * PARAMETERS:
  433. *
  434. * int                    -- The socket file descriptor
  435. * const struct iovec *    -- Pointer to buffer memory
  436. * unsigned                -- Length of available buffer memory
  437. *
  438. * RETURNS:
  439. *
  440. * Bytes read are returned in the given iovec structure.  The integer
  441. * function return value is the number of bytes actually received (-1 = error).
  442. *
  443. */
  444.  
  445. int SK_readv(int s, const struct iovec *iov, int count)
  446. {
  447.     SKg_Config.DoAutoSpin();
  448.     
  449.     CSK_Socket *sock = SKg_SocketTable[s];
  450.  
  451.     if (sock)    {
  452.         CSK_Scatterer scatt(iov, count);
  453.  
  454.         if (scatt)
  455.             return scatt.GetLength(sock->read(scatt.GetBuffer(), scatt.GetBufferLength()));
  456.         else
  457.             return SK_Error(ENOMEM);
  458.     } else
  459.         return -1;
  460. }
  461.  
  462. /****************************************************************************
  463. * FUNCTION:
  464. *
  465. * SK_recv
  466. *
  467. * DESCRIPTION:
  468. *
  469. * Read bytes from the given socket using a plain buffer.
  470. *
  471. * This is equivalent to SK_read(), except that this function is used 
  472. * when conceptually a whole message is being received [SK_read() is 
  473. * used when bytes are read from an ongoing stream].
  474. *
  475. * PARAMETERS:
  476. *
  477. * int                -- The socket file descriptor
  478. * void *            -- Pointer to buffer memory
  479. * unsigned            -- Length of available buffer memory
  480. * int                -- Unused
  481. *
  482. * RETURNS:
  483. *
  484. * Bytes read are returned in the given buffer memory.  The integer
  485. * function return value is the number of bytes actually received (-1 = error).
  486. *
  487. */
  488.  
  489. int SK_recv(int s, void *buffer, int buflen, int flags)
  490. {
  491.     SKg_Config.DoAutoSpin();
  492.     
  493.     int fromlen = 0;
  494.     CSK_Socket *sock = SKg_SocketTable[s];
  495.  
  496.     return sock ? sock->recvfrom(buffer, buflen, flags, nil, &fromlen) : -1;
  497. }
  498.  
  499.  
  500. /****************************************************************************
  501. * FUNCTION:
  502. *
  503. * SK_recvfrom
  504. *
  505. * DESCRIPTION:
  506. *
  507. * Read bytes from the given socket using a plain buffer and fetch internet
  508. * address of sender of bytes.
  509. *
  510. * PARAMETERS:
  511. *
  512. * int                -- The socket file descriptor
  513. * void *            -- Pointer to buffer memory
  514. * unsigned            -- Length of available buffer memory
  515. * int                -- Unused
  516. * struct sockaddr *    -- Pointer to memory for return value
  517. * int *                -- Pointer to memory for return value
  518. *
  519. * RETURNS:
  520. *
  521. * Bytes read are returned in the given buffer memory.  The integer
  522. * function return value is the number of bytes actually received (-1 = error).
  523. * The ip address of the sender is returned in the memory passed in 
  524. * with 'from'.  The length of this ip address is passed back in 'fromlen'.
  525. *
  526. */
  527.  
  528. int SK_recvfrom(int s, void *buffer, int buflen, int flags, struct sockaddr *from, int *fromlen)
  529. {
  530.     SKg_Config.DoAutoSpin();
  531.     
  532.     CSK_Socket *sock = SKg_SocketTable[s];
  533.  
  534.     return sock ? sock->recvfrom(buffer, buflen, flags, from, fromlen) : -1;
  535. }
  536.  
  537.  
  538. /****************************************************************************
  539. * FUNCTION:
  540. *
  541. * SK_recvmsg
  542. *
  543. * DESCRIPTION:
  544. *
  545. * Receive a message on the given socket using a BSD Unix msghdr structure
  546. * (which must contain a properly allocated iovec structure).
  547. *
  548. * PARAMETERS:
  549. *
  550. * int                -- The socket file descriptor
  551. * struct msghdr *    -- The BSD msghdr structure for received message
  552. * int                -- unused
  553. *
  554. * RETURNS:
  555. *
  556. * Bytes read are returned in the given iovec/msghdr memory.  The integer
  557. * function return value is the number of bytes actually received or -1 on
  558. * error, in which case a more specific error return is in the global variable
  559. * errno (see appropriate socket type for details).
  560. *
  561. */
  562.  
  563. int SK_recvmsg(int s, struct msghdr *msg, int flags)
  564. {
  565.     SKg_Config.DoAutoSpin();
  566.     
  567.     CSK_Socket *sock = SKg_SocketTable[s];
  568.  
  569.     if (sock) {
  570.         CSK_Scatterer scatt((struct iovec *) msg->msg_iov, msg->msg_iovlen);
  571.  
  572.         if (scatt)
  573.             return
  574.                 scatt.GetLength(
  575.                     sock->recvfrom(
  576.                         scatt.GetBuffer(),
  577.                         scatt.GetBufferLength(),
  578.                         flags,
  579.                         msg->msg_name,
  580.                         (int *) &msg->msg_namelen));
  581.         else
  582.             return SK_Error(ENOMEM);
  583.     } else
  584.         return -1;
  585. }
  586.  
  587.  
  588. /****************************************************************************
  589. * FUNCTION:
  590. *
  591. * SK_write
  592. *
  593. * DESCRIPTION:
  594. *
  595. * Write bytes to the given socket using a plain buffer.
  596. *
  597. * PARAMETERS:
  598. *
  599. * int                -- The socket file descriptor
  600. * const char *        -- Pointer to buffer memory
  601. * unsigned            -- Length of given buffer memory
  602. *
  603. * RETURNS:
  604. *
  605. * The integer function return value is the number of bytes actually written
  606. * or -1 on error, in which case a more specific error return is in the global
  607. * variable errno (see appropriate socket type for details).
  608. *
  609. */
  610.  
  611. int SK_write(int s, const char *buffer, unsigned buflen)
  612. {
  613.     /* fflush() in the MPW stdio library doesn't take no for an answer.
  614.         Our workaround is to treat a second subsequent ESHUTDOWN or EBADF as 
  615.         an invitation to lie by pretending the write worked.
  616.     */
  617.     
  618.     int    len;
  619.     
  620.     SKg_Config.DoAutoSpin();
  621.     
  622.     CSK_Socket *sock = SKg_SocketTable[s];
  623.  
  624.     if (sock && (len = sock->write((char *) buffer, buflen)) != -1)
  625.         return len;
  626.         
  627.     switch (errno) {
  628.     case EINTR:
  629.     case EWOULDBLOCK:
  630.     case EINPROGRESS:
  631.     case EALREADY:
  632.         break;
  633.     default:
  634.         if (SKg_ErrorSock == s && SKg_ErrorType == errno) {
  635.             if (++SKg_ErrorCount == SKg_ErrorMax) {
  636.                 SKg_ErrorSock = -1;
  637.               
  638.                 return buflen;
  639.             }
  640.           } else {
  641.             SKg_ErrorSock = s;
  642.             SKg_ErrorType = errno;
  643.             SKg_ErrorCount= 1;
  644.         }
  645.     }
  646.      return -1;
  647. }
  648.  
  649.  
  650. /****************************************************************************
  651. * FUNCTION:
  652. *
  653. * SK_writev
  654. *
  655. * DESCRIPTION:
  656. *
  657. * Write bytes to the given socket using a BSD Unix iovec structure.
  658. *
  659. * PARAMETERS:
  660. *
  661. * int                    -- The socket file descriptor
  662. * conststruct iovec *    -- Pointer to buffer memory
  663. * int                    -- Number of bytes to write
  664. *
  665. * RETURNS:
  666. *
  667. * The integer function return value is the number of bytes actually written
  668. * or -1 on error, in which case a more specific error return is in the global
  669. * variable errno (see appropriate socket type for details).
  670. *
  671. */
  672.  
  673. int SK_writev(int s, const struct iovec *iov, int count)
  674. {
  675.     SKg_Config.DoAutoSpin();
  676.     
  677.     CSK_Socket *sock = SKg_SocketTable[s];
  678.  
  679.     if (sock)    {
  680.         CK_Gatherer    gath(iov, count);
  681.  
  682.         if (gath)
  683.             return gath.GetLength(sock->write(gath.GetBuffer(), gath.GetBufferLength()));
  684.         else
  685.             return SK_Error(ENOMEM);
  686.     } else
  687.         return -1;
  688. }
  689.  
  690.  
  691. /****************************************************************************
  692. * FUNCTION:
  693. *
  694. * SK_send
  695. *
  696. * DESCRIPTION:
  697. *
  698. * Write bytes to the given socket using a plain buffer.  This is equivalent
  699. * to SK_write(), except that it is used when bytes written conceptually make
  700. * up a complete message [SK_write() is used to write bytes to an ongoing stream].
  701. *
  702. * PARAMETERS:
  703. *
  704. * int                    -- The socket file descriptor
  705. * struct iovec *        -- Pointer to buffer memory
  706. * int                    -- Length of given buffer
  707. * int                    -- Unused
  708. *
  709. * RETURNS:
  710. *
  711. * The integer function return value is the number of bytes actually written
  712. * or -1 on error, in which case a more specific error return is in the global
  713. * variable errno (see appropriate socket type for details).
  714. *
  715. */
  716.  
  717. int SK_send(int s, void *buffer, int buflen, int flags)
  718. {
  719.     SKg_Config.DoAutoSpin();
  720.     
  721.     CSK_Socket *sock = SKg_SocketTable[s];
  722.  
  723.     return sock ? sock->sendto(buffer, buflen, flags, nil, 0) : -1;
  724. }
  725.  
  726.  
  727. /****************************************************************************
  728. * FUNCTION:
  729. *
  730. * SK_sendto
  731. *
  732. * DESCRIPTION:
  733. *
  734. * Write bytes to the given socket using a plain buffer and get internet
  735. * address of the recipient.
  736. *
  737. * PARAMETERS:
  738. *
  739. * int                        -- The socket file descriptor
  740. * struct iovec *            -- Pointer to buffer memory
  741. * int                        -- Length of given buffer
  742. * int                        -- Unused
  743. * const struct sockaddr *    -- Pointer to memory for ip address return value
  744. * int                        -- Length of memory for ip address return value
  745. *
  746. * RETURNS:
  747. *
  748. * The integer function return value is the number of bytes actually written
  749. * or -1 on error, in which case a more specific error return is in the global
  750. * variable errno (see appropriate socket type for details).  The internet
  751. * address of the recipient is returned in memory passed in 'to', truncated
  752. * if not enough memory was given.
  753. *
  754. */
  755.  
  756. int SK_sendto(int s, void *buffer, int buflen, int flags, const struct sockaddr *to, int tolen)
  757. {
  758.     SKg_Config.DoAutoSpin();
  759.     
  760.     CSK_Socket *sock = SKg_SocketTable[s];
  761.  
  762.     return sock ? sock->sendto(buffer, buflen, flags, (void *) to, tolen) : -1;
  763. }
  764.  
  765.  
  766. /****************************************************************************
  767. * FUNCTION:
  768. *
  769. * SK_sendmsg
  770. *
  771. * DESCRIPTION:
  772. *
  773. * Write a message to the given socket using a BSD Unix msghdr structure,
  774. * which must contain a properly initialized iovec structure.
  775. *
  776. * PARAMETERS:
  777. *
  778. * int                    -- The socket file descriptor
  779. * struct msghdr *        -- Pointer to BSD msghdr structure
  780. * int                    -- Unused
  781. *
  782. * RETURNS:
  783. *
  784. * The integer function return value is the number of bytes actually written
  785. * or -1 on error, in which case a more specific error return is in the global
  786. * variable errno (see appropriate socket type for details).
  787. *
  788. */
  789.  
  790. int SK_sendmsg(int s, const struct msghdr *msg,int flags)
  791. {
  792.     SKg_Config.DoAutoSpin();
  793.     
  794.     CSK_Socket *sock = SKg_SocketTable[s];
  795.  
  796.     if (sock)    {
  797.         CK_Gatherer    gath((struct iovec *) msg->msg_iov, msg->msg_iovlen);
  798.  
  799.         if (gath)
  800.             return
  801.                 gath.GetLength(
  802.                     sock->sendto(
  803.                         gath.GetBuffer(),
  804.                         gath.GetBufferLength(),
  805.                         flags,
  806.                         msg->msg_name,
  807.                         msg->msg_namelen));
  808.         else
  809.             return SK_Error(ENOMEM);
  810.     } else
  811.         return -1;
  812. }
  813.  
  814.  
  815. /****************************************************************************
  816. * FUNCTION:
  817. *
  818. * SK_select
  819. *
  820. * DESCRIPTION:
  821. *
  822. * Check the given read, write, and except file descriptor sets to see
  823. * which items in those sets are ready for reading, ready for writing,
  824. * or have an exceptional condition pending (respectively).  SK_select
  825. * will replace each of these sets with subsets consisting of those
  826. * descriptors that are ready for the requested operation.
  827. *
  828. * PARAMETERS:
  829. *
  830. * int                    -- Number of bits to be checked in each bit mask; 0 to width-1 are checked
  831. *                           This is used to limit compute time by indicating where non-0 bits
  832. *                           are located in the three fd_set parameters below.
  833. * fd_set *                -- Pointer to BSD fd_set (modified for return value / nil = don't care)
  834. * fd_set *                -- Pointer to BSD fd_set (modified for return value / nil = don't care)
  835. * fd_set *                -- Pointer to BSD fd_set (modified for return value / nil = don't care)
  836. * struct timeval *        -- BSD timeval structure giving time out value (nil = unlimited)
  837. *
  838. * RETURNS:
  839. *
  840. * int                    -- The total number of entries in all three return value sets or -1
  841. *                           on error, in which case the global errno contains one of:
  842. *
  843. *     EBADF    One of the descriptor sets specified an invalid descriptor
  844. *     EINTR    An interrupt was encountered before any of the selected events
  845. *            occurred or before timeout limit
  846. *
  847. * NOTES:
  848. *
  849. * This routine is a bit over-commented because I am debugging some code
  850. * that uses it.  Excuuuuse me!
  851. *
  852. */
  853.  
  854. int SK_select(int width, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
  855. {
  856.     CSK_Socket *sock;
  857.     long count;
  858.     int s;
  859.     long starttime, waittime;
  860.     fd_set rd, wd, ed;
  861.     Boolean    r,w,e;
  862.     Boolean *canRead;
  863.     Boolean *canWrite;
  864.     Boolean *exception;
  865.     
  866.     // Initialize
  867.     count = 0;
  868.     FD_ZERO(&rd);
  869.     FD_ZERO(&wd);
  870.     FD_ZERO(&ed);
  871.  
  872.     // Compute time to wait in ticks (1/60th of a second)
  873.     if (timeout) {
  874.         waittime = timeout->tv_sec*60 + timeout->tv_usec/16666;
  875.         starttime = TickCount();
  876.     }
  877.  
  878.     // Check file descriptors for kosherness
  879.     for (s = 0; s < width ; ++s)
  880.         if (    (readfds && FD_ISSET(s,readfds))
  881.             ||    (writefds && FD_ISSET(s,writefds))
  882.             ||    (exceptfds && FD_ISSET(s,exceptfds))
  883.         )
  884.             if (!SKg_SocketTable[s])
  885.                 return SK_Error(EBADF);
  886.  
  887.     
  888.     // Do pre-select
  889.     for (s = 0; s < width ; ++s) {
  890.         sock = SKg_SocketTable[s];
  891.         if (sock != NULL) {
  892.             r = readfds && FD_ISSET(s,readfds);
  893.             w = writefds && FD_ISSET(s,writefds);
  894.             e = exceptfds && FD_ISSET(s,exceptfds);
  895.   
  896.             if (r || w || e)
  897.                  sock->pre_select(r, w, e);
  898.          }
  899.      }
  900.          
  901.     // Compute return sets using first "width" file descriptors in socket table
  902.     // Outer do loop will execute until some entries are placed into some set
  903.     // or until timeout is reached
  904.     do {
  905.         // Look through socket table for sockets ready for requested operations
  906.         for (s = 0; s < width ; ++s)  {
  907.             // Get socket
  908.             sock = SKg_SocketTable[s];
  909.             if (sock != NULL) {
  910.                 // Init temporary flags
  911.                 r = false;
  912.                 w = false;
  913.                 e = false;
  914.  
  915.                 // Set temporary return values to <> nil iff the caller was
  916.                 // interested in these operations for this specific file descriptor
  917.                 canRead = (readfds && FD_ISSET(s,readfds)) ? &r : nil;
  918.                 canWrite = (writefds && FD_ISSET(s,writefds)) ? &w : nil;
  919.                 exception = (exceptfds && FD_ISSET(s,exceptfds)) ? &e : nil;
  920.  
  921.                 // If user was interested in any operation for this socket,
  922.                 // then call the socket to check status on each that was
  923.                 // of interest
  924.                 if (canRead || canWrite || exception) {
  925.                     // Call socket and increment count by number of requested
  926.                     // operations that this socket is ready for
  927.                     count += sock->select(canRead, canWrite, exception);
  928.  
  929.                     // For each operation returning TRUE, add this socket
  930.                     // to the appropriate return value bit vector set
  931.                     if (r)
  932.                         FD_SET(s,&rd);
  933.                     if (w)
  934.                         FD_SET(s,&wd);
  935.                     if (e)
  936.                         FD_SET(s,&ed);
  937.                 }
  938.             }
  939.         }
  940.         
  941.         // Kill time & give up one time slice; if user hit cancel, then 
  942.         // errno is set = EINTR and select returns immediately with
  943.         // a -1 return value
  944.         SPIN(false, SKk_SELECT, 0);
  945.         
  946.     }  while(!count &&(!timeout || TickCount() - starttime < waittime));
  947.  
  948.     // Do post-select
  949.      for (s = 0; s < width ; ++s) {
  950.          sock = SKg_SocketTable[s];
  951.         if (sock != NULL) {
  952.             r = readfds && FD_ISSET(s,readfds);
  953.             w = writefds && FD_ISSET(s,writefds);
  954.             e = exceptfds && FD_ISSET(s,exceptfds);
  955.  
  956.              if (r || w || e)
  957.                  sock->post_select(r, w, e);
  958.          }
  959.      }
  960.          
  961.  
  962.     // Set return file descriptor sets
  963.     if (readfds)
  964.         *readfds = rd;
  965.     if (writefds)
  966.         *writefds = wd;
  967.     if (exceptfds)
  968.         *exceptfds = ed;
  969.  
  970.     // Return number of entries total in all returned sets
  971.     return count;
  972. }
  973.  
  974.  
  975. /****************************************************************************
  976. * FUNCTION:
  977. *
  978. * SK_getsockname
  979. *
  980. * DESCRIPTION:
  981. *
  982. * Get name of given socket
  983. *
  984. * PARAMETERS:
  985. *
  986. * int                    -- The socket file descriptor
  987. * struct sockaddr *        -- Pointer to memory for name return value
  988. * int *                    -- Pointer to memory for return value (initialized
  989. *                           to space available in name return buffer)
  990. *
  991. * RETURNS:
  992. *
  993. * The integer function return value -1 on error, in which case a more 
  994. * specific error return is in the global variable errno (see appropriate 
  995. * socket type for details).
  996. *
  997. */
  998.  
  999. int SK_getsockname(int s, struct sockaddr *name, int *namelen)
  1000. {
  1001.     CSK_Socket *sock = SKg_SocketTable[s];
  1002.  
  1003.     return sock ? sock->getsockname(name, namelen) : -1;
  1004. }
  1005.  
  1006.  
  1007. /****************************************************************************
  1008. * FUNCTION:
  1009. *
  1010. * SK_getpeername
  1011. *
  1012. * DESCRIPTION:
  1013. *
  1014. * Get name of the remote peer connected to given socket
  1015. *
  1016. * PARAMETERS:
  1017. *
  1018. * int                    -- The socket file descriptor
  1019. * struct sockaddr *        -- Pointer to memory for return value
  1020. * int *                    -- Pointer to memory for return value (initialized
  1021. *                           to space available in name return buffer)
  1022. *
  1023. * RETURNS:
  1024. *
  1025. * The integer function return value -1 on error, in which case a more 
  1026. * specific error return is in the global variable errno (see appropriate 
  1027. * socket type for details).
  1028. *
  1029. */
  1030.  
  1031. int SK_getpeername(int s, struct sockaddr *name, int *namelen)
  1032. {
  1033.     CSK_Socket *sock = SKg_SocketTable[s];
  1034.  
  1035.     return sock ? sock->getpeername(name, namelen) : -1;
  1036. }
  1037.  
  1038.  
  1039. /****************************************************************************
  1040. * FUNCTION:
  1041. *
  1042. * SK_shutdown
  1043. *
  1044. * DESCRIPTION:
  1045. *
  1046. * Shut down part or all of a connection on a given socket
  1047. *
  1048. * PARAMETERS:
  1049. *
  1050. * int            -- The socket file descriptor
  1051. * int            -- How to shut down : If 0, then further receives 
  1052. *                   will be disallowed.  If 1,  then further sends will 
  1053. *                   be disallowed.  If 2, then further sends and receives 
  1054. *                   will be disallowed.
  1055. *
  1056. * RETURNS:
  1057. *
  1058. * The integer function return value -1 on error or 0 on success.
  1059. *
  1060. */
  1061.  
  1062. int SK_shutdown(int s, int how)
  1063. {
  1064.     CSK_Socket *sock = SKg_SocketTable[s];
  1065.  
  1066.     return sock ? sock->shutdown(how) : -1;
  1067. }
  1068.  
  1069.  
  1070. /****************************************************************************
  1071. * FUNCTION:
  1072. *
  1073. * SK_fcntl
  1074. *
  1075. * DESCRIPTION:
  1076. *
  1077. * Operate on (or control) the given socket
  1078. *
  1079. * PARAMETERS:
  1080. *
  1081. * int            -- The socket file descriptor
  1082. * int            -- Command - see specific socket types for details
  1083. * int            -- Argument - see specific socket types for details
  1084. *
  1085. * RETURNS:
  1086. *
  1087. * The integer function return value -1 on error or 0 on success.
  1088. *
  1089. */
  1090.  
  1091. int SK_fcntl(int s, unsigned int cmd, int arg)
  1092. {
  1093.     CSK_Socket *sock = SKg_SocketTable[s];
  1094.  
  1095.     if (sock)
  1096.         return (cmd == F_DUPFD) ? SKg_SocketTable.Install(sock, arg) : sock->fcntl(cmd, arg);
  1097.     else
  1098.         return -1;
  1099. }
  1100.  
  1101.  
  1102. /****************************************************************************
  1103. * FUNCTION:
  1104. *
  1105. * SK_dup
  1106. *
  1107. * DESCRIPTION:
  1108. *
  1109. * ???
  1110. *
  1111. * PARAMETERS:
  1112. *
  1113. * int            -- The socket file descriptor
  1114. *
  1115. * RETURNS:
  1116. *
  1117. * ???
  1118. *
  1119. */
  1120.  
  1121. int SK_dup(int s)
  1122. {
  1123.     CSK_Socket *sock = SKg_SocketTable[s];
  1124.  
  1125.     return sock ? SKg_SocketTable.Install(sock) : -1;
  1126. }
  1127.  
  1128.  
  1129. /****************************************************************************
  1130. * FUNCTION:
  1131. *
  1132. * SK_dup2
  1133. *
  1134. * DESCRIPTION:
  1135. *
  1136. * ???
  1137. *
  1138. * PARAMETERS:
  1139. *
  1140. * int            -- The socket file descriptor
  1141. * int            -- ???
  1142. *
  1143. * RETURNS:
  1144. *
  1145. * ???
  1146. *
  1147. */
  1148.  
  1149. int SK_dup2(int s, int s1)
  1150. {
  1151.     CSK_Socket *sock = SKg_SocketTable[s];
  1152.  
  1153.     if (!sock)
  1154.         return -1;
  1155.  
  1156.     if (SKg_SocketTable[s1])
  1157.         SKg_SocketTable.Remove(s1);
  1158.  
  1159.     return SKg_SocketTable.Install(sock, s1);
  1160. }
  1161.  
  1162.  
  1163. /****************************************************************************
  1164. * FUNCTION:
  1165. *
  1166. * SK_ioctl
  1167. *
  1168. * DESCRIPTION:
  1169. *
  1170. * ???
  1171. *
  1172. * PARAMETERS:
  1173. *
  1174. * int            -- The socket file descriptor
  1175. * int            -- ???
  1176. * char *        -- ???
  1177. *
  1178. * RETURNS:
  1179. *
  1180. * ???
  1181. *
  1182. */
  1183.  
  1184. int SK_ioctl(int s, unsigned int request, char *argp)
  1185. {
  1186.     CSK_Socket *sock = SKg_SocketTable[s];
  1187.  
  1188.     return sock ? sock->ioctl(request, argp) : -1;
  1189. }
  1190.  
  1191.  
  1192. /****************************************************************************
  1193. * FUNCTION:
  1194. *
  1195. * SK_getsockopt
  1196. *
  1197. * DESCRIPTION:
  1198. *
  1199. * ???
  1200. *
  1201. * PARAMETERS:
  1202. *
  1203. * int            -- The socket file descriptor
  1204. * int            -- ???
  1205. * int            -- ???
  1206. * char *        -- ???
  1207. * int *            -- ???
  1208. *
  1209. * RETURNS:
  1210. *
  1211. * ???
  1212. *
  1213. */
  1214.  
  1215. int SK_getsockopt(int s, int level, int optname, void *optval, int * optlen)
  1216. {
  1217.     CSK_Socket *sock = SKg_SocketTable[s];
  1218.  
  1219.     return sock ? sock->getsockopt(level, optname, optval, optlen) : -1;
  1220. }
  1221.  
  1222.  
  1223. /****************************************************************************
  1224. * FUNCTION:
  1225. *
  1226. * SK_setsockopt
  1227. *
  1228. * DESCRIPTION:
  1229. *
  1230. * ???
  1231. *
  1232. * PARAMETERS:
  1233. *
  1234. * int            -- The socket file descriptor
  1235. * int            -- ???
  1236. * int            -- ???
  1237. * char *        -- ???
  1238. * int             -- ???
  1239. *
  1240. * RETURNS:
  1241. *
  1242. * ???
  1243. *
  1244. */
  1245.  
  1246. int SK_setsockopt(int s, int level, int optname, void *optval, int optlen)
  1247. {
  1248.     CSK_Socket *sock = SKg_SocketTable[s];
  1249.  
  1250.     return sock ? sock->setsockopt(level, optname, optval, optlen) : -1;
  1251. }
  1252.  
  1253.  
  1254. /****************************************************************************
  1255. * FUNCTION:
  1256. *
  1257. * SK_fstat
  1258. *
  1259. * DESCRIPTION:
  1260. *
  1261. * ???
  1262. *
  1263. * PARAMETERS:
  1264. *
  1265. * int                -- The socket file descriptor
  1266. * struct stat *        -- ???
  1267. *
  1268. * RETURNS:
  1269. *
  1270. * ???
  1271. *
  1272. */
  1273.  
  1274. int SK_fstat(int s, struct stat * buf)
  1275. {
  1276.     CSK_Socket *sock = SKg_SocketTable[s];
  1277.  
  1278.     return sock ? sock->fstat(buf) : -1;
  1279. }
  1280.  
  1281.  
  1282. /****************************************************************************
  1283. * FUNCTION:
  1284. *
  1285. * SK_lseek
  1286. *
  1287. * DESCRIPTION:
  1288. *
  1289. * ???
  1290. *
  1291. * PARAMETERS:
  1292. *
  1293. * int                -- The socket file descriptor
  1294. * long                -- ???
  1295. * int                -- ???
  1296. *
  1297. * RETURNS:
  1298. *
  1299. * ???
  1300. *
  1301. */
  1302.  
  1303. long SK_lseek(int s, long offset, int whence)
  1304. {
  1305.     CSK_Socket *sock = SKg_SocketTable[s];
  1306.  
  1307.     return sock ? sock->lseek(offset, whence) : -1;
  1308. }
  1309.  
  1310.  
  1311. /****************************************************************************
  1312. * FUNCTION:
  1313. *
  1314. * SK_ftruncate
  1315. *
  1316. * DESCRIPTION:
  1317. *
  1318. * ???
  1319. *
  1320. * PARAMETERS:
  1321. *
  1322. * int                -- The socket file descriptor
  1323. * long              -- ???
  1324. *
  1325. * RETURNS:
  1326. *
  1327. * ???
  1328. *
  1329. */
  1330.  
  1331. int SK_ftruncate(int s, long offset)
  1332. {
  1333.     CSK_Socket *sock = SKg_SocketTable[s];
  1334.  
  1335.     return sock ? sock->ftruncate(offset) : -1;
  1336. }
  1337.  
  1338.  
  1339. /****************************************************************************
  1340. * FUNCTION:
  1341. *
  1342. * SK_isatty
  1343. *
  1344. * DESCRIPTION:
  1345. *
  1346. * Check whether the given socket is a tty (real or virtual ascii terminal)
  1347. *
  1348. * PARAMETERS:
  1349. *
  1350. * int                -- The socket file descriptor
  1351. *
  1352. * RETURNS:
  1353. *
  1354. * TRUE (<> 0) when the socket is a tty, or FALSE (0) when it is not.
  1355. *
  1356. */
  1357.  
  1358. int SK_isatty(int s)
  1359. {
  1360.     CSK_Socket *sock = SKg_SocketTable[s];
  1361.  
  1362.     return sock ? sock->isatty() : -1;
  1363. }
  1364.  
  1365.  
  1366. /****************************************************************************
  1367. * FUNCTION:
  1368. *
  1369. * SK_Error
  1370. *
  1371. * DESCRIPTION:
  1372. *
  1373. * Set the global errno to the given value and return -1
  1374. *
  1375. * PARAMETERS:
  1376. *
  1377. * int                -- The error value
  1378. *
  1379. * RETURNS:
  1380. *
  1381. * Always -1.
  1382. *
  1383. */
  1384.  
  1385. int SK_Error(int err)
  1386. {
  1387.     errno =    err;
  1388.  
  1389.     return -1;
  1390. }
  1391.  
  1392.  
  1393. /****************************************************************************
  1394. * FUNCTION:
  1395. *
  1396. * SK_Error_nil
  1397. *
  1398. * DESCRIPTION:
  1399. *
  1400. * Set the global errno to the given value and return nil
  1401. *
  1402. * PARAMETERS:
  1403. *
  1404. * int                -- The error value
  1405. *
  1406. * RETURNS:
  1407. *
  1408. * Always nil.
  1409. *
  1410. */
  1411.  
  1412. void *SK_Error_nil(int err)
  1413. {
  1414.     errno =    err;
  1415.  
  1416.     return nil;
  1417. }
  1418.  
  1419.  
  1420. /****************************************************************************
  1421. * FUNCTION:
  1422. *
  1423. * SK_SetSpin
  1424. *
  1425. * DESCRIPTION:
  1426. *
  1427. * Set the spin routine to use during idle times waiting on sockets
  1428. *
  1429. * PARAMETERS:
  1430. *
  1431. * SKt_SpinFn        -- The spin function to use
  1432. *
  1433. */
  1434.  
  1435. void SK_SetSpin(SKt_SpinFn routine)
  1436. {
  1437.     SKg_SpinRoutine = routine;
  1438. }
  1439.  
  1440.  
  1441. /****************************************************************************
  1442. * FUNCTION:
  1443. *
  1444. * SK_GetSpin
  1445. *
  1446. * DESCRIPTION:
  1447. *
  1448. * Get the spin routine used during idle times waiting on sockets
  1449. *
  1450. * RETURNS:
  1451. *
  1452. * SKt_SpinFn        -- The spin function to use
  1453. *
  1454. */
  1455.  
  1456. SKt_SpinFn SK_GetSpin()
  1457. {
  1458.     return SKg_SpinRoutine;
  1459. }
  1460.  
  1461.  
  1462. /****************************************************************************
  1463. * FUNCTION:
  1464. *
  1465. * SK_SetEvents
  1466. *
  1467. * DESCRIPTION:
  1468. *
  1469. * Set the event dispatch vector to use with the default SK spin routine
  1470. *
  1471. * PARAMETERS:
  1472. *
  1473. * SKt_EvtHandler *        -- The event handler call vector
  1474. *
  1475. * RETURNS:
  1476. *
  1477. * Error value (0 = success; else failure).
  1478. */
  1479.  
  1480. int SK_SetEvents(SKt_EvtHandler *table)
  1481. {
  1482.     short    evt;
  1483.  
  1484.     SKg_EventHandler = table;
  1485.     SKg_EvtMask = 0;
  1486.  
  1487.     /* Set up event mask according to values in event handler table */
  1488.     for (evt = 0; evt<16; ++evt)
  1489.         if (SKg_EventHandler[evt])
  1490.             SKg_EvtMask    |=    1 << evt;
  1491.  
  1492.     return 0;
  1493. }
  1494.  
  1495.  
  1496. /****************************************************************************
  1497. * FUNCTION:
  1498. *
  1499. * SK_GetEvents
  1500. *
  1501. * DESCRIPTION:
  1502. *
  1503. * Get the event dispatch vector used with the default SK spin routine
  1504. *
  1505. * RETURNS:
  1506. *
  1507. * SKt_EvtHandler *    -- Pointer to the first item in the event handler call vector
  1508. */
  1509.  
  1510. SKt_EvtHandler *SK_GetEvents(void)
  1511. {
  1512.     return SKg_EventHandler;
  1513. }
  1514.  
  1515.  
  1516. /**************************************************************************/ 
  1517. /* CSK_Configuration members */
  1518.  
  1519. /* xFirstTime static member variable for initialization */
  1520. Boolean CSK_Configuration::xFirstTime = false;
  1521.  
  1522. /* Callback for handling unsupported apple events */
  1523. pascal OSErr 
  1524. SK_UnsupportedAEVT(AppleEvent* /*messagein*/, AppleEvent* /*reply*/, long /*refIn*/)
  1525. {
  1526.     return errAEEventNotHandled;
  1527. }
  1528.  
  1529. /*************************************************************************** *
  1530. * FUNCTION: 
  1531. *
  1532. * CSK_Configuration::CSK_Configuration()
  1533. *
  1534. * DESCRIPTION:
  1535. *
  1536. * Constructor for CSK_Configuration class
  1537. *
  1538. */
  1539.  
  1540. CSK_Configuration::CSK_Configuration()
  1541. {
  1542.     const long    stdEvt[] = {
  1543.         kAEOpenApplication,
  1544.         kAEOpenDocuments,
  1545.         kAEQuitApplication,
  1546.         kAEPrintDocuments
  1547.     };
  1548.     
  1549.     fTCPDaemon=    SKk_TCPDaemon;
  1550.     fUDPDaemon=    SKk_UDPDaemon;
  1551.     
  1552.     fAutoSpin = SKk_AutoSpin;    // Do automatic spin on read/write
  1553.     fVersion = SKk_Version;
  1554.     
  1555.     if (!xFirstTime) {
  1556.         xFirstTime = true;
  1557.     
  1558.         if (IsDaemon()) 
  1559.             for (int i = 0; i < sizeof(stdEvt); i++) 
  1560.                 AEInstallEventHandler(
  1561.                     kCoreEventClass, 
  1562.                     stdEvt[i], 
  1563.                     AEEventHandlerProcPtr(SK_UnsupportedAEVT), 
  1564.                     0, 
  1565.                     false);
  1566.     }
  1567. }
  1568.  
  1569. /*************************************************************************** *
  1570. * FUNCTION:
  1571. *
  1572. * CSK_Configuration::DoAutoSpin()
  1573. *
  1574. * DESCRIPTION:
  1575. *
  1576. * Execute the SK "spin" function
  1577. *
  1578. */
  1579.  
  1580. inline void CSK_Configuration::DoAutoSpin() const 
  1581. {
  1582.     if (fAutoSpin)
  1583.         SAFESPIN(0, SKk_AUTO_SPIN, fAutoSpin);
  1584. }
  1585.  
  1586. /*************************************************************************** *
  1587. * FUNCTION:
  1588. *
  1589. * CSK_Configuration::IsDaemon()
  1590. *
  1591. * DESCRIPTION:
  1592. *
  1593. * Return TRUE if this application is a daemon (and not a regular stand-alone)
  1594. *
  1595. */
  1596.  
  1597. Boolean CSK_Configuration::IsDaemon() const
  1598. {
  1599.     return fTCPDaemon || fUDPDaemon;
  1600. }
  1601.  
  1602.  
  1603. /**************************************************************************/ 
  1604. /**************************************************************************/ 
  1605. /* CSK_SocketDomain members */
  1606.  
  1607. /* Static array of socket domains */
  1608. CSK_SocketDomain *CSK_SocketDomain::xDomains[SKk_MAX_DOMAIN];
  1609.  
  1610.  
  1611. /****************************************************************************
  1612. * FUNCTION:
  1613. *
  1614. * CSK_SocketDomain::CSK_SocketDomain
  1615. *
  1616. * DESCRIPTION:
  1617. *
  1618. * Constructor for this class
  1619. *
  1620. * PARAMETERS:
  1621. *
  1622. * int domain        -- the socket identifier (= index into xDomains static array
  1623. *                       at which this socket is to be placed)
  1624. *
  1625. */
  1626.  
  1627. CSK_SocketDomain::CSK_SocketDomain(int domain)
  1628. {
  1629.     ASSERT(xDomains[domain] == NULL);
  1630.     xDomains[domain] = this;
  1631. }
  1632.  
  1633. /****************************************************************************
  1634. * FUNCTION:
  1635. *
  1636. * CSK_SocketDomain::~CSK_SocketDomain
  1637. *
  1638. * DESCRIPTION:
  1639. *
  1640. * Destructor for this class
  1641. *
  1642. */
  1643.  
  1644. CSK_SocketDomain::~CSK_SocketDomain()
  1645. {
  1646. }
  1647.  
  1648. /****************************************************************************
  1649. * FUNCTION:
  1650. *
  1651. * CSK_SocketDomain::Domain
  1652. *
  1653. * DESCRIPTION:
  1654. *
  1655. * Return the socket corresponding with a given identifier for this domain
  1656. *
  1657. * PARAMETERS:
  1658. *
  1659. * int                 -- the socket identifier (= index into xDomains static array)
  1660. *
  1661. * RETURNS:
  1662. *
  1663. * CK_SocketDomain    -- a pointer to the requested socket (or nil if none found)
  1664. *
  1665. */
  1666.  
  1667. CSK_SocketDomain *CSK_SocketDomain::Domain(int domain)
  1668. {
  1669.     ASSERT(domain >= 0 && domain < SKk_MAX_DOMAIN);
  1670.     if (xDomains[domain] == NULL)
  1671.         return nil;
  1672.     else
  1673.         return xDomains[domain];
  1674. }
  1675.  
  1676. /*************************************************************************** *
  1677. * FUNCTION:
  1678. *
  1679. * CSK_SocketDomain::open
  1680. *
  1681. * DESCRIPTION:
  1682. *
  1683. * Default implementation of open() -- just returns an error
  1684. *
  1685. * PARAMETERS:
  1686. *
  1687. * const char*        -- unused
  1688. * int                -- unused
  1689. *
  1690. * RETURNS:
  1691. *
  1692. *
  1693. * NOTES:
  1694. *
  1695. *
  1696. */
  1697.  
  1698. CSK_Socket * CSK_SocketDomain::open(const char *, int)
  1699. {
  1700.     UNIMPLEMENTED;
  1701.     return(NULL);
  1702. }
  1703.  
  1704.  
  1705. /*************************************************************************** *
  1706. * FUNCTION:
  1707. *
  1708. * CSK_SocketDomain::open
  1709. *
  1710. * DESCRIPTION:
  1711. *
  1712. * Default implementation of socket() -- just returns an error
  1713. *
  1714. * PARAMETERS:
  1715. *
  1716. * int                -- unused
  1717. * short                -- unused
  1718. *
  1719. * RETURNS:
  1720. *
  1721. *
  1722. * NOTES:
  1723. *
  1724. *
  1725. */
  1726.  
  1727. CSK_Socket * CSK_SocketDomain::socket(int, short)
  1728. {
  1729.     UNIMPLEMENTED;
  1730.     return(NULL);
  1731. }
  1732.  
  1733.  
  1734. /**************************************************************************/ 
  1735. /**************************************************************************/ 
  1736. /* CLurkSocket members */
  1737.  
  1738. class CLurkSocket : public CSK_Socket {
  1739. public:
  1740.     CLurkSocket(int descr);
  1741. };
  1742.  
  1743.  
  1744. /*************************************************************************** *
  1745. * FUNCTION:
  1746. *
  1747. * CLurkSocket::CLurkSocket
  1748. *
  1749. * DESCRIPTION:
  1750. *
  1751. * Constructor for this class
  1752. *
  1753. * PARAMETERS:
  1754. *
  1755. * int                 -- lurking socket's file descriptor
  1756. *
  1757. */
  1758.  
  1759. CLurkSocket::CLurkSocket(int descr) : CSK_Socket()
  1760. {
  1761.     fLurking = true;
  1762.     fLurkDescr = char(descr);
  1763. }
  1764.  
  1765.  
  1766. /**************************************************************************/ 
  1767. /**************************************************************************/ 
  1768. /* CSK_SocketTable members */
  1769.  
  1770. /*************************************************************************** *
  1771. * FUNCTION:
  1772. *
  1773. * CSK_SocketTable::CSK_SocketTable
  1774. *
  1775. * DESCRIPTION:
  1776. *
  1777. * Constructor for this class
  1778. *
  1779. */
  1780.  
  1781. CSK_SocketTable::CSK_SocketTable()
  1782. {
  1783.     // Allocate first 4 "lurking" sockets for TCP and UDP daemon programs
  1784.     // (that is, any that are not a full stand-alone program)
  1785.     for (int i = 0; (i < 3) & !STANDALONE; i++)
  1786.         if (SKg_Config.IsDaemon()) {
  1787.             fSockets[i]    =    new CLurkSocket(i);
  1788.         } else {
  1789. // -- NOT NEEDED SINCE WE DEAL ONLY WITH TCP/UDP.  I think. -------
  1790. //          (want to avoid including FileSockets stuff!)
  1791. //    
  1792. //            fSockets[i]    = FileSockets.stdopen(i);
  1793. //
  1794. //            ++fSockets[i]->fRefCount;
  1795. // ----------------------------------------------------------------
  1796.             UNIMPLEMENTED;
  1797.         }
  1798. }
  1799.  
  1800.  
  1801. /*************************************************************************** *
  1802. * FUNCTION:
  1803. *
  1804. * CSK_SocketTable::~CSK_SocketTable
  1805. *
  1806. * DESCRIPTION:
  1807. *
  1808. * Destructor for this class
  1809. *
  1810. */
  1811.  
  1812. /*
  1813. FILE *_lastbuf = _iob + _NFILE;
  1814. */
  1815.  
  1816. CSK_SocketTable::~CSK_SocketTable()
  1817. {
  1818.     int i;
  1819.  
  1820.     // Flush and vclose stdio files (necessary to flush buffers)
  1821.     // This implementation is not nice, but who cares ?
  1822.     // In case you wonder, _iob is defined in <stdio.h>
  1823. // -- NOT NEEDED SINCE WE DEAL ONLY WITH TCP/UDP.  I think. -------
  1824. //    for (i = 0; _iob+i<_lastbuf; i++)
  1825. //        fflush(_iob+i);
  1826. //
  1827. //    for (i = 0; _iob+i<_lastbuf; i++)
  1828. //        fclose(_iob+i);
  1829. // ----------------------------------------------------------------
  1830.  
  1831.     // Close all sockets
  1832.     for (i = 0; i<SKk_MaxFD; ++i)
  1833.         if (fSockets[i])
  1834.             SK_close(i);
  1835. }
  1836.  
  1837.  
  1838. /*************************************************************************** *
  1839. * FUNCTION:
  1840. *
  1841. * int CSK_SocketTable::Install
  1842. *
  1843. * DESCRIPTION:
  1844. *
  1845. * Install a socket into this socket table
  1846. *
  1847. * PARAMETERS:
  1848. *
  1849. * CSK_Socket *                -- Pointer to socket to install
  1850. * int                        -- Minimum file descriptor to use for socket
  1851. *
  1852. * RETURNS:
  1853. *
  1854. * File descriptor assigned to given socket
  1855. *
  1856. */
  1857.  
  1858. int CSK_SocketTable::Install(CSK_Socket * sock, int start)
  1859. {
  1860.     short fd;
  1861.  
  1862.     ASSERT(start >= 0 && start < SKk_MaxFD);
  1863.  
  1864.     for (fd=start; fd<SKk_MaxFD; ++fd)
  1865.         if (!fSockets[fd])    {
  1866.             fSockets[fd] = sock;
  1867.             ++sock->fRefCount;
  1868.             return fd;
  1869.         }
  1870.  
  1871.     return SK_Error(EMFILE);
  1872. }
  1873.  
  1874.  
  1875. /*************************************************************************** *
  1876. * FUNCTION:
  1877. *
  1878. * CSK_SocketTable::Possess
  1879. *
  1880. * DESCRIPTION:
  1881. *
  1882. * Replace a lurking socket of given descriptor with the given socket
  1883. *
  1884. * PARAMETERS:
  1885. *
  1886. * int                -- File descriptor for socket
  1887. * CSK_Socket *        -- Pointer to socket
  1888. *
  1889. */
  1890.  
  1891. void CSK_SocketTable::Possess(int descr, CSK_Socket * sock)
  1892. {
  1893.     int i;
  1894.     
  1895.     for (i = 0; i<SKk_MaxFD; ++i)
  1896.         if (fSockets[i]->fLurking && fSockets[i]->fLurkDescr == descr) {
  1897.             SK_close(i);
  1898.             fSockets[i] = sock;
  1899.             if (sock != NULL)
  1900.                 ++sock->fRefCount;
  1901.         }
  1902. }
  1903.  
  1904.  
  1905. /*************************************************************************** *
  1906. * FUNCTION:
  1907. *
  1908. * CSK_SocketTable::Remove
  1909. *
  1910. * DESCRIPTION:
  1911. *
  1912. * Remove the socket with given file descriptor from this socket table
  1913. *
  1914. * PARAMETERS:
  1915. *
  1916. * int            -- File descriptor for socket to remove
  1917. *
  1918. * RETURNS:
  1919. *
  1920. * int            -- Error or 0 if no error
  1921. *
  1922. * NOTES:
  1923. *
  1924. *
  1925. */
  1926.  
  1927. int CSK_SocketTable::Remove(int fd)
  1928. {
  1929.     CSK_Socket *    sock;
  1930.  
  1931.     if (fd<0 || fd >= SKk_MaxFD || !(sock = fSockets[fd]))
  1932.         return SK_Error(EBADF);
  1933.  
  1934.     fSockets[fd]     =    nil;
  1935.  
  1936.     if (!--sock->fRefCount)
  1937.         delete sock;
  1938.  
  1939.     return 0;
  1940. }
  1941.  
  1942.  
  1943. /*************************************************************************** *
  1944. * FUNCTION:
  1945. *
  1946. * CSK_SocketTable::operator[]
  1947. *
  1948. * DESCRIPTION:
  1949. *
  1950. * Index [] operator for socket tables.  Returns the socket with given file
  1951. * descriptor or nil if not found.
  1952. *
  1953. * PARAMETERS:
  1954. *
  1955. * int                -- The file descriptor of socket to locate in table
  1956. *
  1957. * RETURNS:
  1958. *
  1959. * CSK_Socket *        -- Pointer to socket with given descriptor (or nil if not found)
  1960. *
  1961. * NOTES:
  1962. *
  1963. * Note that this function will wait, calling the SK idle "spin" routine
  1964. * if the given socket is lurking.  When the socket is no longer lurking, the
  1965. * pointer to the socket will be returned.
  1966. *
  1967. */
  1968.  
  1969. CSK_Socket * CSK_SocketTable::operator[](int fd)
  1970. {
  1971.     CSK_Socket * sock;
  1972.  
  1973.     restart:
  1974.     if (fd<0 || fd >= SKk_MaxFD || !(sock = fSockets[fd]))    {
  1975.         SK_Error(EBADF);
  1976.         return nil;
  1977.     } else if (sock->fLurking) {
  1978.         SPINP(fSockets[fd]->fLurking, SKk_MISC, 0);
  1979.         goto restart; 
  1980.     } else
  1981.         return sock;
  1982. }
  1983.  
  1984.  
  1985. /**************************************************************************/ 
  1986. /**************************************************************************/ 
  1987. /* CSK_Feature members */
  1988.  
  1989.  
  1990. /*************************************************************************** *
  1991. * FUNCTION:
  1992. *
  1993. * CSK_Feature::CSK_Feature
  1994. *
  1995. * DESCRIPTION:
  1996. *
  1997. * Constructor for this class
  1998. *
  1999. * PARAMETERS:
  2000. *
  2001. * short             -- Macintosh trap number
  2002. * TrapType            -- Type of trap
  2003. *
  2004. */
  2005.  
  2006. CSK_Feature::CSK_Feature(short trapNum, TrapType tTyp)
  2007. {
  2008.     fGood = (NGetTrapAddress(trapNum, tTyp) != NGetTrapAddress(_Unimplemented, ToolTrap));
  2009. }
  2010.  
  2011.  
  2012. /*************************************************************************** *
  2013. * FUNCTION:
  2014. *
  2015. * CSK_Feature::CSK_Feature
  2016. *
  2017. * DESCRIPTION:
  2018. *
  2019. * Constructor for this class
  2020. *
  2021. * PARAMETERS:
  2022. *
  2023. * OSType             -- 
  2024. * long                -- 
  2025. *
  2026. */
  2027.  
  2028. CSK_Feature::CSK_Feature(OSType type, long value)
  2029. {
  2030.     long attr;
  2031.  
  2032.     fGood = (!Gestalt(type, &attr) && (attr >= value));
  2033. }
  2034.  
  2035.  
  2036. /*************************************************************************** *
  2037. * FUNCTION:
  2038. *
  2039. * CSK_Feature::CSK_Feature
  2040. *
  2041. * DESCRIPTION:
  2042. *
  2043. * Constructor for this class
  2044. *
  2045. * PARAMETERS:
  2046. *
  2047. * OSType             -- 
  2048. * long                -- 
  2049. * long                --
  2050. *
  2051. */
  2052.  
  2053. CSK_Feature::CSK_Feature(OSType type, long mask, long value)
  2054. {
  2055.     long attr;
  2056.  
  2057.     fGood = (!Gestalt(type, &attr) && ((attr & mask) == value));
  2058. }
  2059.  
  2060.  
  2061. /*************************************************************************** *
  2062. * FUNCTION:
  2063. *
  2064. * CSK_Feature::CSK_Feature
  2065. *
  2066. * DESCRIPTION:
  2067. *
  2068. * Constructor for this class
  2069. *
  2070. * PARAMETERS:
  2071. *
  2072. * const CSK_Feature &         -- 
  2073. * SKt_OSErrInitializer        -- 
  2074. *
  2075. */
  2076.  
  2077. CSK_Feature::CSK_Feature(const CSK_Feature & precondition, SKt_OSErrInitializer init)
  2078. {
  2079.     fGood = (precondition && !init());
  2080. }
  2081.  
  2082.  
  2083. /*************************************************************************** *
  2084. * FUNCTION:
  2085. *
  2086. * CSK_Feature::CSK_Feature
  2087. *
  2088. * DESCRIPTION:
  2089. *
  2090. * Constructor for this class
  2091. *
  2092. * PARAMETERS:
  2093. *
  2094. * SKt_OSErrInitializer        -- 
  2095. *
  2096. */
  2097.  
  2098. CSK_Feature::CSK_Feature(SKt_OSErrInitializer init)
  2099. {
  2100.     fGood = !init();
  2101. }
  2102.  
  2103.  
  2104. /*************************************************************************** *
  2105. * FUNCTION:
  2106. *
  2107. * CSK_Feature::CSK_Feature
  2108. *
  2109. * DESCRIPTION:
  2110. *
  2111. * Constructor for this class
  2112. *
  2113. * PARAMETERS:
  2114. *
  2115. * const CSK_Feature &         -- 
  2116. * SKt_VoidInitializer        -- 
  2117. *
  2118. */
  2119.  
  2120. CSK_Feature::CSK_Feature(const CSK_Feature & precondition, SKt_VoidInitializer init)
  2121. {
  2122.     if (precondition)    {
  2123.         fGood = true;
  2124.         init();
  2125.     } else
  2126.         fGood = false;
  2127. }
  2128.  
  2129.  
  2130. /*************************************************************************** *
  2131. * FUNCTION:
  2132. *
  2133. * CSK_Feature::CSK_Feature
  2134. *
  2135. * DESCRIPTION:
  2136. *
  2137. * Constructor for this class
  2138. *
  2139. * PARAMETERS:
  2140. *
  2141. * SKt_VoidInitializer        -- 
  2142. *
  2143. */
  2144.  
  2145. CSK_Feature::CSK_Feature(SKt_VoidInitializer init)
  2146. {
  2147.     fGood = true;
  2148.     init();
  2149. }
  2150.  
  2151.  
  2152. /*************************************************************************** *
  2153. * FUNCTION:
  2154. *
  2155. * CSK_Feature::CSK_Feature
  2156. *
  2157. * DESCRIPTION:
  2158. *
  2159. * Constructor for this class
  2160. *
  2161. * PARAMETERS:
  2162. *
  2163. * const CSK_Feature &        --
  2164. * const CSK_Feature &        -- 
  2165. *
  2166. */
  2167.  
  2168. CSK_Feature::CSK_Feature(const CSK_Feature & cond1, const CSK_Feature & cond2)
  2169. {
  2170.     fGood = (cond1 && cond2);
  2171. }
  2172.  
  2173.  
  2174. /**************************************************************************/ 
  2175. /**************************************************************************/ 
  2176. /* Default spin function & associated utilities */
  2177.  
  2178. /* Borrowed from tech note 263 */
  2179.  
  2180. /* Constants used with default spin function */
  2181.  
  2182. #define kMaskModifiers      0xFE00         // we need the modifiers without the
  2183.                                            // command key for KeyTrans
  2184. #define kMaskVirtualKey     0x0000FF00     // get virtual key from event message
  2185.                                            // for KeyTrans
  2186. #define kUpKeyMask          0x0080
  2187. #define kShiftWord          8              // we shift the virtual key to mask it
  2188.                                            // into the keyCode for KeyTrans
  2189. #define kMaskASCII1         0x00FF0000     // get the key out of the ASCII1 byte
  2190. #define kMaskASCII2         0x000000FF     // get the key out of the ASCII2 byte
  2191. #define kPeriod             0x2E           // ascii for a period
  2192.  
  2193.  
  2194. /*************************************************************************** *
  2195. * FUNCTION:
  2196. *
  2197. * SK_CmdPeriod
  2198. *
  2199. * DESCRIPTION:
  2200. *
  2201. * Check the given event record to see if it is a command-period keyboard event.
  2202. *
  2203. * PARAMETERS:
  2204. *
  2205. * EventRecord *            -- The Macintosh event record to check
  2206. *
  2207. * RETURNS:
  2208. *
  2209. * Boolean                -- TRUE if event record is command-period
  2210. *
  2211. * NOTES:
  2212. *
  2213. * Should replace this later to use Jonathan's GUI toolkit instead of being
  2214. * Mac-specific
  2215. *
  2216. */
  2217.  
  2218. static Boolean SK_CmdPeriod(EventRecord *theEvent)
  2219. {
  2220.       Boolean fTimeToQuit;
  2221.       short keyCode;
  2222.       long virtualKey, keyInfo, lowChar, highChar, state, keyCId;
  2223.       Handle hKCHR;
  2224.     Ptr KCHRPtr;
  2225.  
  2226.     fTimeToQuit = false;
  2227.  
  2228.     if (((*theEvent).what == keyDown) || ((*theEvent).what == autoKey)) {
  2229.  
  2230.         // see if the command key is down.  If it is, find out the ASCII
  2231.         // equivalent for the accompanying key.
  2232.  
  2233.         if ((*theEvent).modifiers & cmdKey ) {
  2234.  
  2235.             virtualKey = ((*theEvent).message & kMaskVirtualKey) >> kShiftWord;
  2236.             // And out the command key and Or in the virtualKey
  2237.             keyCode    = short(((*theEvent).modifiers & kMaskModifiers) | virtualKey);
  2238.             state      = 0;
  2239.  
  2240.             hKCHR = nil;  /* set this to nil before starting */
  2241.              KCHRPtr = (Ptr)GetEnvirons(smKCHRCache);
  2242.  
  2243.             if ( !KCHRPtr ) {
  2244.                 keyCId = GetScript(short(GetEnvirons(smKeyScript)), smScriptKeys);
  2245.  
  2246.                 hKCHR   = GetResource('KCHR',short(keyCId));
  2247.                 KCHRPtr = *hKCHR;
  2248.             }
  2249.  
  2250.             if (KCHRPtr) {
  2251.                 keyInfo = KeyTrans(KCHRPtr, keyCode, &state);
  2252.                 if (hKCHR)
  2253.                     ReleaseResource(hKCHR);
  2254.             } else
  2255.                 keyInfo = (*theEvent).message;
  2256.  
  2257.             lowChar =  keyInfo &  kMaskASCII2;
  2258.             highChar = (keyInfo & kMaskASCII1) >> 16;
  2259.             if (lowChar == kPeriod || highChar == kPeriod)
  2260.                 fTimeToQuit = true;
  2261.  
  2262.         }  // end the command key is down
  2263.     }  // end key down event
  2264.  
  2265.     return( fTimeToQuit );
  2266. }
  2267.  
  2268.  
  2269. /*************************************************************************** *
  2270. * FUNCTION:
  2271. *
  2272. * SK_DefaultSpinRoutine
  2273. *
  2274. * DESCRIPTION:
  2275. *
  2276. * The default "spin" routine for SK.  This is used to provide limited multi-
  2277. * threading during waits for communications ports, etc.  The routine gives
  2278. * up time slices to the system and other applications and also processes
  2279. * basic GUI events to allow cancel (command-.) and switching of application
  2280. * into background while it is processing.
  2281. *
  2282. * This spin routine will call event handlers in the SKg_EventHandler[]
  2283. * array when they are present for specific types of events (the index in
  2284. * the array is the Macintosh event type used in WaitNextEvent()).  If
  2285. * no handler is included for kHighLevelEvent events, then AEProcessAppleEvent()
  2286. * is called directly.
  2287. *
  2288. * You should use SK_SetEvents() to set the event handler array when SK
  2289. * is initialized.
  2290. *
  2291. * PARAMETERS:
  2292. *
  2293. * SKt_SpinMsg            -- 
  2294. * long                    --
  2295. *
  2296. * RETURNS:
  2297. *
  2298. * int                    -- error return (0 = no error)
  2299. *
  2300. * NOTES:
  2301. *
  2302. * Could replace this later to use DSG's GUI portability layer instead of being
  2303. * Mac-specific.
  2304. *
  2305. * Should rewrite this to check what parts of the toolkit were initialized
  2306. * and bail out gracefully if some vital initialization is missing.
  2307. *
  2308. */
  2309.  
  2310. /* 
  2311. * This MUST be extern "C" so that dispatching works properly (at least 
  2312. * under THINK C++ 6.0 there is a bug (?) with converting between regular 
  2313. * C and C++ functions in non-debug code) 
  2314. */
  2315. extern "C" {
  2316.  
  2317. /* Local utility function */
  2318. Boolean SK_Interrupt()
  2319. {
  2320.     EvQElPtr eventQ;
  2321.  
  2322.     for (eventQ = (EvQElPtr) GetEvQHdr()->qHead; eventQ; )
  2323.          if (SK_CmdPeriod((EventRecord *) &eventQ->evtQWhat))
  2324.             return true;
  2325.         else
  2326.             eventQ = (EvQElPtr)eventQ->qLink;
  2327.     
  2328.     return false;
  2329. }
  2330.  
  2331. int SK_DefaultSpinRoutine(SKt_SpinMsg msg, long arg)
  2332. {
  2333.     static Boolean inForeground = true;
  2334.     static Boolean lastEventCheck = TickCount();
  2335.     WindowPtr win;
  2336.     EventRecord ev;
  2337.  
  2338. //  Commented out because we lack SpinCursor, which was only defined in MPW
  2339. //
  2340. //    if (inForeground)
  2341. //        SpinCursor(msg == SKk_AUTO_SPIN ? short(arg) : 1);
  2342.     
  2343.     if (!inForeground || STANDALONE)    {
  2344.         if (SK_Interrupt())
  2345.             goto interrupt;
  2346.  
  2347.         if (SKg_WNE)    {
  2348.             if (WaitNextEvent(osMask|highLevelEventMask|mDownMask|SKg_EvtMask, &ev, 1, nil)) {
  2349.                    // Process the event, if any
  2350.                 switch (ev.what) {
  2351.                     case mouseDown:
  2352.                         if (!SKg_EventHandler || !SKg_EventHandler[mouseDown])
  2353.                             if (FindWindow(ev.where, &win) == inSysWindow)
  2354.                                 SystemClick(&ev, win);
  2355.  
  2356.                         break;
  2357.                     case osEvt:
  2358.                         if (ev.message & 1)
  2359.                             inForeground    =    true;
  2360.                         else
  2361.                             inForeground    =    false;
  2362.                         break;
  2363.                     case kHighLevelEvent:
  2364.                         if (!SKg_EventHandler || !SKg_EventHandler[kHighLevelEvent])
  2365.                             if (SKg_AppleEvents)    // Actually pretty likely, if we get HL Events
  2366.                                 if (AEProcessAppleEvent(&ev))
  2367.                                     return -1;
  2368.                         break;
  2369.                     default:
  2370.                         break;
  2371.                     }
  2372.                 if ((ev.what >= 0) && (ev.what < SKk_MaxEvents) && (SKg_EventHandler != NULL) && 
  2373.                        (SKg_EventHandler[ev.what] != NULL))
  2374.                     SKg_EventHandler[ev.what](&ev);
  2375.                 }
  2376.  
  2377.         } else {
  2378.             long     endTicks;
  2379.  
  2380.             SystemTask();
  2381.             GetNextEvent(SKg_EvtMask, &ev);
  2382.  
  2383.             if ((ev.what >= 0) && (ev.what < SKk_MaxEvents) && (SKg_EventHandler != NULL) && 
  2384.                 (SKg_EventHandler[ev.what] != NULL))
  2385.                 SKg_EventHandler[ev.what](&ev);
  2386.  
  2387.             Delay(1, &endTicks);   /* Probably not a good way to do this! */
  2388.         }
  2389.     }
  2390.     
  2391.     return 0;
  2392.  
  2393.  
  2394.     /********/
  2395.     interrupt:
  2396.  
  2397.     FlushEvents(-1, 0);
  2398.  
  2399.     return -1;
  2400.     }
  2401.  
  2402. }
  2403.  
  2404.  
  2405. /* end of SK_Dispatch.cc */
  2406.